package com.wizo.csb.iostream;

import java.io.*;

/**
 * This is a special InputStream to avoid the huge-size objects problem. We allocate a specified
 * size of memory and use it to cyclically access this memory to imitate accessing a huge-size 
 * object.
 * @author Wizo
 *
 */

public class CyclicalByteArrayInputStream extends InputStream{

	protected byte[] _contents;
	protected int _position;
	protected int _mark;
	protected long _streamLength; // The length of this InputStream
	protected int _arrayLength; // The length of the byte array
	protected long _rest; // The rest count of bytes not read yet 
	protected long _markRest;

	public CyclicalByteArrayInputStream(long streamLength){
		int HexKB = 1024*16;
		_streamLength = streamLength;
		_position = 0;
		_rest = streamLength;

		if(streamLength<=HexKB){
			_arrayLength = (int)streamLength;
		}else{
			_arrayLength = HexKB;
		}

		_contents = new byte[_arrayLength];
		_contents[_arrayLength-1] = 10;
	}

	@Override
	public synchronized int read() throws IOException {
		if(_rest<=0)
			return -1;

		_rest--;
		if(_position<_arrayLength)
			return _contents[_position++] & 0xff;
		else if(_position==_arrayLength){
			_position = 1;
			return _contents[0] & 0xff;
		}else{
			// Theoretically it won't happen
			return -1;
		}
	}

	public synchronized String readLine() throws IOException{
		if(_rest<=0)
			return null;

		StringBuffer buffer = new StringBuffer();
		int temp;
		while((temp=read())!=10){
			buffer.append(Integer.toHexString(temp));
		}
		//buffer.append("\n");

		return buffer.toString();
	}

	public synchronized int read(byte[] b, int off, int len){
		 if(b==null) {                                                               
             throw new NullPointerException();
         }else if(off<0 || len<0 || len > b.length-off){
             throw new IndexOutOfBoundsException();
         }

		 if(_rest<0)
			return -1;
		 if(len>_rest)
			len = (int)_rest;

		 int rest = len;
		 int tempOff = off;
		 while(rest>0){
			 if(rest<=_arrayLength-_position){
				 System.arraycopy(_contents, _position, b, tempOff, rest);
				 _position = (_position+rest)%_arrayLength;
				 _rest -= rest;
				 return len;
			 }else{
				 int temp = _arrayLength-_position;
				 System.arraycopy(_contents, _position, b, tempOff, temp);
				 tempOff += temp;
				 rest -= temp;
				 _position = 0;
				 _rest -= temp;
			 }
		 }
         return -1;
	}

	public synchronized long skip(long n){
		if(n>_rest)
			n = _rest;
		if(n<0)
			return 0;

		int temp = (int)(n%_arrayLength);		
		_position = (_position+temp)%_arrayLength;
		_rest -= n;

		return n;
	}

	public synchronized int available(){
		return (int)_rest;
	}

	public boolean markSupporter(){
		return true;
	}

	public void mark(int reallimit){
		_mark = _position;
		_markRest = _rest;
	}

	public synchronized void reset(){
		_position = _mark;
		_rest = _markRest;
	}

	public void close() throws IOException{
		//Nothing to do
	}

//	public static void main(String[] args){
//		CyclicalByteArrayInputStream input = new CyclicalByteArrayInputStream(33*1024);
//		BufferedWriter writer = null;
//		File file = new File("abc.txt");
//		if(!file.exists()){
//			try{
//				file.createNewFile();
//			}catch(IOException e){
//				e.printStackTrace();
//			}
//		}
//		
//		try{
//			writer = new BufferedWriter(new FileWriter(file));
//			int i;
//			while((i=input.read())!=-1){
//				writer.write(i);
//			}
//		}catch(IOException e){
//			e.printStackTrace();
//		}finally{
//			try{
//				writer.close();
//			}catch(IOException e){
//				e.printStackTrace();
//			}
//		}
//		
//		try {
//			BufferedReader reader = new BufferedReader(new FileReader(file));
//			int lines = 0;
//			while(reader.readLine()!=null){
//				lines++;
//			}
//			System.out.println(lines);
//		} catch (IOException e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		}
//	}
}